package dev.ece.core.vertex;

import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;

import dev.ece.core.clearup.ClearUpGLRubbish;
import dev.ece.core.clearup.ClearUpGLRubbishManager;
import dev.ece.util.lib.Vector2f;
import dev.ece.util.lib.Vector3f;
import dev.ece.util.lib.Vector4f;

public class VAO implements ClearUpGLRubbish {
	
	private int vao_buffer_handler;
	
	private int index;
	
	private Vector<ClearUpGLRubbish> vbos = new Vector<ClearUpGLRubbish>();
	
	
	public VAO() {
		vao_buffer_handler = GL30.glGenVertexArrays();
	}
	
	public void bind() {
		GL30.glBindVertexArray(this.vao_buffer_handler);
	}
	
	public int bindVertexArrayBuffer(VBO vbo, int size) {
		vbo.bind();
		GL20.glVertexAttribPointer(index, size, GL11.GL_FLOAT, false, 0, 0);
		GL20.glEnableVertexAttribArray(index);
		vbos.add(vbo);
		return index ++;
	}
	
	public int bindElementArrayBuffer(EBO ebo, int size) {
		ebo.bind();
		GL20.glVertexAttribPointer(index, size, ebo.getType(), false, 0, 0);
		GL20.glEnableVertexAttribArray(index);
		vbos.add(ebo);
		return index ++;
	}
	
	public int bindVertexArrayBuffer(Vector4f[] vectors) {
		VBO vbo = VBO.newInstance(vectors);
		return bindVertexArrayBuffer(vbo, 4);
	}
	
	public int bindVertexArrayBuffer4f(List<Vector4f> vectors) {
		VBO vbo = VBO.newInstance4f(vectors);
		return bindVertexArrayBuffer(vbo, 4);
	}
	
	public int bindVertexArrayBuffer(Vector3f[] vectors) {
		VBO vbo = VBO.newInstance(vectors);
		return bindVertexArrayBuffer(vbo, 3);
	}
	
	public int bindVertexArrayBuffer3f(List<Vector3f> vectors) {
		VBO vbo = VBO.newInstance3f(vectors);
		return bindVertexArrayBuffer(vbo, 3);
	}
	
	public int bindVertexArrayBuffer(Vector2f[] vectors) {
		VBO vbo = VBO.newInstance(vectors);
		return bindVertexArrayBuffer(vbo, 2);
	}
	
	public int bindVertexArrayBuffer2f(List<Vector2f> vectors) {
		VBO vbo = VBO.newInstance2f(vectors);
		return bindVertexArrayBuffer(vbo, 2);
	}
	
	public int bindVertexArrayBuffer(float[] vectors) {
		VBO vbo = VBO.newInstance(vectors);
		return bindVertexArrayBuffer(vbo, 1);
	}
	
	public int bindVertexArrayBuffer1f(List<Float> vectors) {
		VBO vbo = VBO.newInstance1f(vectors);
		return bindVertexArrayBuffer(vbo, 1);
	}
	
	public int bindElementArrayBuffer(short[] indice, int size) {
		EBO ebo = EBO.newInstance(indice);
		return bindElementArrayBuffer(ebo, size);
	}
	
	public int bindElementArrayBufferShort(List<Short> indice, int size) {
		EBO ebo = EBO.newInstanceShort(indice);
		return bindElementArrayBuffer(ebo, size);
	}
	
	public int bindElementArrayBuffer(int[] indice, int size) {
		EBO ebo = EBO.newInstance(indice);
		return bindElementArrayBuffer(ebo, size);
	}
	
	public int bindElementArrayBufferInt(List<Integer> indice, int size) {
		EBO ebo = EBO.newInstanceInt(indice);
		return bindElementArrayBuffer(ebo, size);
	}
	
	public static void unbind() {
		GL30.glBindVertexArray(0);
	}
	
	public void finish() {
		VBO.unbind();
		EBO.unbind();
		VAO.unbind();
	}
	
	public void destroy() {
		ClearUpGLRubbishManager.push(this);
		Iterator<ClearUpGLRubbish>  it = this.vbos.iterator();
		while(it.hasNext()) {
			ClearUpGLRubbishManager.push(it.next());
		}
		this.vbos.clear();
		this.index = 0;
	}
	
	@Override
	public void clearup() {
		GL30.glDeleteVertexArrays(vao_buffer_handler);
	}

}
